package com.ddm.service.impl.webImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ddm.constant.MessageConstant;
import com.ddm.entity.webEntity.PaymentRecord;
import com.ddm.entity.webEntity.Plan;
import com.ddm.entity.webEntity.UserSubscribe;
import com.ddm.enumeration.OrderStatusEnum;
import com.ddm.exception.DataErrorException;
import com.ddm.mapper.PaymentMapper;
import com.ddm.result.Result;
import com.ddm.service.webService.PaymentService;
import com.ddm.service.webService.PlanService;
import com.ddm.service.webService.UserSubscribeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

@Slf4j
@Service
public class PaymentServiceImpl extends ServiceImpl<PaymentMapper, PaymentRecord> implements PaymentService {

    @Autowired
    private PaymentMapper paymentMapper;
    @Resource
    private PlanService planService;
    @Resource
    private UserSubscribeService subscriptionService;

    /**
     * 修改订单支付状态
     * @param orderNo 订单编号
     * @param newStatus 新状态（枚举值：PAID, CANCELLED等）
     * @return 更新后的订单记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentRecord updatePaymentStatus(String orderNo, String newStatus) {
        // 1. 参数校验
        if (orderNo == null || orderNo.trim().isEmpty()) {
            throw new IllegalArgumentException("订单编号不能为空");
        }
        if (newStatus == null || newStatus.trim().isEmpty()) {
            throw new IllegalArgumentException("新状态不能为空");
        }
        OrderStatusEnum newStatusEnum;
        try {
            newStatusEnum = OrderStatusEnum.valueOf(newStatus.trim());
        }catch (IllegalArgumentException e){
            log.error("无效的订单状态: {}", newStatus);
            throw new IllegalArgumentException("无效的订单状态: " + newStatus);
        }
        // 3. 查询订单
        PaymentRecord paymentRecord = getPaymentByOrderNo(orderNo);
        if (paymentRecord == null) {
            log.error("订单不存在，orderNo: {}", orderNo);
            throw new IllegalArgumentException("订单不存在，orderNo: " + orderNo);
        }
        OrderStatusEnum oldStatusEnum = paymentRecord.getOrderStatus();
        if (oldStatusEnum.equals(newStatusEnum)) {
            log.info("订单状态无需变更，当前状态与目标状态一致，orderNo: {}", orderNo);
            return paymentRecord;
        }
        // 5.2 已支付→取消：需要处理退款逻辑（这里仅做日志记录，实际项目需对接支付网关）
        if (OrderStatusEnum.PAID.equals(oldStatusEnum)
                && (OrderStatusEnum.CANCELLED.equals(newStatusEnum) || OrderStatusEnum.REFUNDED.equals(newStatusEnum))) {
            log.warn("订单需处理退款/取消，orderNo: {}, 金额: {}", orderNo, paymentRecord.getAmount());
            // TODO: 对接支付网关的退款接口（如支付宝/微信退款），此处需补充实际退款逻辑
        }
        // 6. 执行更新（核心优化：不依赖返回值，以二次查询为准）
        PaymentRecord updateRecord = new PaymentRecord();
        updateRecord.setId(paymentRecord.getId()); // 仅更新必要字段，避免覆盖无关值
        updateRecord.setOrderStatus(newStatusEnum);

        // 执行更新并打印返回值（便于排查）
        int updateRows = baseMapper.updateById(updateRecord);
        log.info("订单更新SQL执行结果，orderNo: {}, 影响行数: {}", orderNo, updateRows);

        // 7. 二次查询数据库，确认状态是否已更新（核心修复点）
        PaymentRecord updatedRecord = baseMapper.selectById(paymentRecord.getId());
        if (updatedRecord == null) {
            log.error("更新后查询订单失败，orderNo: {}", orderNo);
            throw new RuntimeException("更新后查询订单失败");
        }
        if (!newStatusEnum.equals(updatedRecord.getOrderStatus())) {
            log.error("订单状态更新未生效，orderNo: {}, 预期状态: {}, 实际状态: {}",
                    orderNo, newStatusEnum, updatedRecord.getOrderStatus());
            throw new RuntimeException("订单状态更新未生效，请重试");
        }

        // 8. 更新成功，返回最新记录
        log.info("订单状态更新成功，orderNo: {}, 最终状态: {}", orderNo, updatedRecord.getOrderStatus());
        return updatedRecord;
    }

    @Override
    public PaymentRecord getPaymentByOrderNo(String orderNo) {
        //1、空值校验
        if(orderNo==null||"".equals(orderNo)){
            return null;
        }
        // 2. 构造条件查询
        LambdaQueryWrapper<PaymentRecord> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getOrderNo,orderNo);
        wrapper.orderByAsc(PaymentRecord::getOrderNo);

        List<PaymentRecord> paymentRecords=list(wrapper);
        return paymentRecords.isEmpty() ? null : paymentRecords.get(0);
    }

    @Override
    public IPage<PaymentRecord> queryPaymentPage(int pageNum, int pageSize, String userId) {
        // 1. 分页参数校验
        if (pageNum<=0||pageSize<=0){
            return null;
        }
        if(userId==null||"".equals(userId)){
            return null;
        }
        // 2. 构造分页对象
        Page<PaymentRecord> page=new Page<>(pageNum,pageSize);
        // 3. 构造条件：支持按用户筛选
        LambdaQueryWrapper<PaymentRecord> wrapper=new LambdaQueryWrapper<>();
        if(Objects.nonNull(userId)){
            wrapper.eq(PaymentRecord::getUserId,userId);
        }
        // 4. 执行分页查询
        return page(page, wrapper);
    }

    /**
     * 新增订单核心逻辑
     */
    @Override
    @Transactional(rollbackFor = Exception.class) // 事务保证
    public PaymentRecord createPaymentRecord(Integer userId, Integer planId, String orderStatus) {
        // 0. 校验用户和套餐合法性（复用原有逻辑）
        if (userId == null || planId == null) {
            throw new IllegalArgumentException("用户ID和套餐ID不能为空");
        }
        Plan plan = planService.getById(planId);
        if (plan == null) {
            log.error("套餐不存在，planId: {}", planId);
            throw new IllegalArgumentException("套餐不存在，planId: " + planId);
        }
        // 1. 验证订单状态
        OrderStatusEnum statusEnum;
        try {
            statusEnum = OrderStatusEnum.valueOf(orderStatus);
        } catch (IllegalArgumentException e) {
            log.error("无效订单状态：{}", orderStatus);
            throw new IllegalArgumentException("无效的订单状态：" + orderStatus); // 抛异常让Controller捕获
        }
        // 2. 查询用户该套餐的未支付订单（UNPAID）
        PaymentRecord existingRecord = baseMapper.selectOne(new QueryWrapper<PaymentRecord>()
                .eq("user_id", userId)
                .eq("subscription_id", planId)
                .eq("order_status", OrderStatusEnum.UNPAID) // 只查未支付状态
                .last("limit 1")); // 确保只返回一条
        // 3. 存在未支付订单：直接更新状态（如从UNPAID→PAID）
        if (existingRecord != null) {
            log.info("存在未支付订单，更新状态。订单ID: {}, 用户ID: {}, 套餐ID: {}",
                    existingRecord.getId(), userId, planId);

            // 更新状态和必要字段
            existingRecord.setOrderStatus(statusEnum);
            // 执行更新
            int update = baseMapper.updateById(existingRecord);
            if (update > 0) {
                return existingRecord; // 返回更新后的订单
            } else {
                PaymentRecord updated = baseMapper.selectById(existingRecord.getId());
                if (updated != null && statusEnum.equals(updated.getOrderStatus())) {
                    log.info("订单状态更新成功（影响行数异常，但实际状态已变更），订单ID: {}", existingRecord.getId());
                    return updated;
                } else {
                    log.error("更新订单状态失败，订单ID: {}，影响行数: {}", existingRecord.getId(), updated);
                    throw new RuntimeException("更新订单状态失败");
                }
            }
        }
        // 4. 不存在未支付订单：创建新订单（仅当状态为UNPAID时创建，避免直接创建已支付订单）
        if (!OrderStatusEnum.UNPAID.equals(statusEnum)) {
            log.error("创建订单失败：不存在未支付订单，且目标状态不是UNPAID");
            throw new IllegalArgumentException("请先创建未支付订单");
        }
        // 4.1 校验是否有有效订阅
        boolean hasValidSubscription = checkValidSubscription(userId, planId);
        if (hasValidSubscription) {
            String message = "无需重复订阅：用户ID=" + userId + "已订阅套餐ID=" + planId + "，且当前在有效期内";
            log.warn(message);
            throw new IllegalArgumentException(message);
        }
        // 4.2 校验价格
        BigDecimal amount = plan.getDiscountPrice();
        if (amount == null || amount.compareTo(BigDecimal.ZERO) <0) {
            log.error("套餐价格不合法，planId: {}", planId);
            throw new IllegalArgumentException("套餐价格不合法，planId: " + planId);
        }
        // 4.3 生成新订单
        String orderNo = generateOrderNo();
        PaymentRecord paymentRecord = new PaymentRecord();
        paymentRecord.setUserId(userId);
        paymentRecord.setSubscriptionId(planId);
        paymentRecord.setOrderNo(orderNo);
        paymentRecord.setAmount(amount);
        paymentRecord.setOrderStatus(statusEnum);
        paymentRecord.setCreateTime(new Date());
        paymentRecord.setPaymentMethod("DEFAULT");

        // 6. 保存订单（优化判断方式：通过主键是否生成判断成功）
        int insert = baseMapper.insert(paymentRecord); // 直接调用mapper的insert方法
        if (insert > 0) {
            // 插入成功后，MyBatis-Plus会自动回填自增主键
            log.info("订单保存成功，orderNo: {}, id: {}", orderNo, paymentRecord.getId());
            return paymentRecord; // 返回带主键的实体
        }
        // 7. 保存失败的额外校验（防止insert返回1但实际失败的情况）
        PaymentRecord saved = baseMapper.selectOne(new QueryWrapper<PaymentRecord>().eq("order_no", orderNo));
        if (saved != null) {
            return saved;
        }
        log.error("订单保存失败");
        return null; // 明确返回null表示失败
    }

    /**
     * 获取订单列表（根据用户ID、订单状态、创建时间分页查询）
     */
    @Override
    public IPage<PaymentRecord> getPaymentList(String userId, String orderStatus, LocalDate startDate, LocalDate endDate, Integer page, Integer pageSize) {
        // 1. 构建MyBatis-Plus分页对象
        IPage<PaymentRecord> queryPage = new Page<>(page, pageSize);
        // 2. 构建多条件查询Wrapper
        LambdaQueryWrapper<PaymentRecord> queryWrapper = new LambdaQueryWrapper<>();
        // 筛选条件1：用户ID（非空才添加，按业务需求，这里用精确匹配）
        if (userId != null && !userId.trim().isEmpty()) {
            queryWrapper.eq(PaymentRecord::getUserId, userId.trim());
        }
        // 筛选条件2：订单状态（非空才添加，精确匹配，与数据库存储的状态值一致）
        if (orderStatus != null && !orderStatus.trim().isEmpty()) {
            queryWrapper.eq(PaymentRecord::getOrderStatus, orderStatus.trim());
        }
        if (startDate != null && endDate != null) {
            LocalDateTime startDataTime= LocalDateTime.of(startDate, LocalTime.MIN);
            LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.MAX);
            queryWrapper.ge(PaymentRecord::getCreateTime, startDate);
            queryWrapper.le(PaymentRecord::getCreateTime, endDateTime);
        }
        // 排序：默认按创建时间降序（最新订单在前），创建时间相同则按订单号降序
        queryWrapper.orderByDesc(PaymentRecord::getCreateTime);
        // 3. 执行分页查询（MyBatis-Plus自动处理分页和总条数）
        return paymentMapper.selectPage(queryPage, queryWrapper);
    }

    @Override
    public Result<String> deletePaymentRecord(String orderNo) {
        if(orderNo==null || orderNo.trim().isEmpty()) {
            log.error("删除支付记录：订单编号为空");
            throw new DataErrorException(MessageConstant.ERROR_DATA);
        }
        orderNo = orderNo.trim();

        LambdaQueryWrapper<PaymentRecord> orderWrapper = new LambdaQueryWrapper<>();
        orderWrapper.eq(PaymentRecord::getOrderNo, orderNo);
        PaymentRecord paymentRecord=baseMapper.selectOne(orderWrapper);

        if (paymentRecord == null) {
            log.error("删除支付记录失败：订单编号={}对应的订单不存在", orderNo);
            return Result.error("订单不存在，无法删除支付记录");
        }
        baseMapper.deleteById(paymentRecord.getId());
        // 关键：二次查询验证删除结果（判断记录是否真的被删除）
        PaymentRecord deletedRecord = paymentMapper.selectOne(orderWrapper);
        if (deletedRecord == null) {
            // 二次查询不到 → 确实删除成功
            log.info("删除支付记录成功：订单编号={}，支付记录ID={}（二次查询确认已删除）", orderNo, paymentRecord.getId());
            return Result.success("删除订单编号=%s的支付记录成功".formatted(orderNo));
        } else {
            // 二次查询还能查到 → 删除失败
            log.error("删除支付记录失败：订单编号={}，支付记录ID={}（二次查询仍存在）", orderNo, paymentRecord.getId());
            return Result.error("删除订单编号=%s的支付记录失败，请重试".formatted(orderNo));
        }
    }

    // 工具方法：生成订单号
    private String generateOrderNo() {
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
        String timestamp = String.valueOf(System.currentTimeMillis()).substring(6);
        return "ORD" + uuid + timestamp;
    }

    /**
     * 新增：校验用户是否已存在有效订阅
     * @param userId 用户ID
     * @param planId 套餐ID
     * @return true=已存在有效订阅，false=不存在
     */
    private boolean checkValidSubscription(Integer userId, Integer planId) {
        LocalDate now = LocalDate.now(); // 当前日期
        // 查询subscription表：同一用户+同一套餐+未过期（end_date >= 当前日期）
        QueryWrapper<UserSubscribe> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)        // 匹配用户ID
                .eq("plan_id", planId)        // 匹配套餐ID
                .ge("end_date", now);         // 有效期内（结束日期 >= 当前日期）

        // 统计符合条件的订阅记录数
        int count =subscriptionService.count(queryWrapper);
        return count > 0; // >0表示存在有效订阅
    }

}
